home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / hypercar / xfcn / spttool.cpt / Support Tools eXternals 1.2.5 / card_35218.txt < prev    next >
Text File  |  1990-11-13  |  18KB  |  452 lines

  1. -- card: 35218 from stack: in.5
  2. -- bmap block id: 10518
  3. -- flags: 0000
  4. -- background id: 3858
  5. -- name: FolderContents
  6. ----- HyperTalk script -----
  7. on CloseCard
  8.   put empty into cd fld "folder list"
  9.   set the scroll of cd fld "folder list" to 0
  10.   pass CloseCard
  11. end CloseCard
  12.  
  13. on HideObjects
  14.   hide cd fld "folder list"
  15.   hide cd btn "try it!"
  16. end HideObjects
  17.  
  18. on ShowObjects
  19.   show cd fld "folder list"
  20.   show cd btn "try it!"
  21. end ShowObjects
  22.  
  23.  
  24. -- part 1 (button)
  25. -- low flags: 00
  26. -- high flags: A002
  27. -- rect: left=82 top=292 right=326 bottom=175
  28. -- title width / last selected line: 0
  29. -- icon id / first selected line: 0 / 0
  30. -- text alignment: 1
  31. -- font id: 0
  32. -- text size: 12
  33. -- style flags: 8192
  34. -- line height: 16
  35. -- part name: Try It!
  36. ----- HyperTalk script -----
  37. on mouseUp
  38.   global errGlobal
  39.   put FolderPath("Choose a folder to list.") into folderName
  40.   if folderName = empty then exit mouseUp
  41.   put FolderContents(folderName, "Both", "noDialog:errGlobal") into FolderInfo
  42.   if errGlobal Γëá empty then
  43.     answer "Error: ΓÇ£" & errGlobal & "ΓÇ¥"
  44.     put empty into errGlobal
  45.   else
  46.     put FolderInfo into cd fld "folder list"
  47.   end if
  48. end mouseUp
  49.  
  50.  
  51.  
  52.  
  53. -- part 2 (field)
  54. -- low flags: 00
  55. -- high flags: 0007
  56. -- rect: left=19 top=117 right=288 bottom=236
  57. -- title width / last selected line: 0
  58. -- icon id / first selected line: 0 / 0
  59. -- text alignment: 0
  60. -- font id: 4
  61. -- text size: 9
  62. -- style flags: 0
  63. -- line height: 12
  64. -- part name: folder list
  65.  
  66.  
  67. -- part contents for background part 38
  68. ----- text -----
  69. 22/50
  70.  
  71. -- part contents for background part 20
  72. ----- text -----
  73. FolderContents - An XFCN to return the files/folders contained in a specified folder.
  74.  
  75. FolderContents(Pathname, ┬½,"Files"|"Folders"|"Both"┬╗ ┬½"noDialog:"errorGlobal┬╗)
  76. PATHNAME : a path to a folder to examine
  77. PARAMETER 2 should be the literal string      "Files", "Folders" or "Both".
  78.  
  79. This XFCN will return a carraige return delimited list (one file/folder per line) of all files, folders, or both files and folders (as per parameter 2) within the specified directory.  The names of all folders will end in a ":".  The default is to list "both" files and folders.  The next version will be A/UX compatible.
  80.  
  81.  
  82. -- part contents for background part 42
  83. ----- text -----
  84. { FolderContents(pathname ┬½,"Files"|"Folders"|"Both"┬╗ ┬½,"nodialog":errGlobal┬╗)     }
  85. { XFCN to return the file/folder names in the specified path given in the     }
  86. { first parameter.                                                                 }
  87. { Second parameter specifies what will be returned.  Only files, only         }
  88. { folders, or both files & folders can be returned in the list.                  }
  89. {}
  90. {   Written by:   Anup Murarka       Eric Carlson                  }
  91. {               ALINK:  SKEPTIC       ALINK:  cyNic           }
  92. {                                   CIS:  76004,3356}
  93. {}
  94. {               We are part of the Support Tools Development Group,    }
  95. {               Apple Computer, Inc.     }
  96. {}
  97. {               please DO NOT contack Mac DTS for support of this code!   }
  98. {}
  99. {               please DO contact the authors for support of this code!  }
  100. {}
  101. {               Send comments, bug reports, requests to any of the above    }
  102. {               E-mail addresses or to:}
  103. {}
  104. {                           (one of us)                    }
  105. {                           Apple Computer, Inc.         }
  106. {                           900 E. Hamilton, Ave.       }
  107. {                           Campbell, CA   95008       }
  108. {                           M/S 72-L                     }
  109. {}
  110. {   Copyright:    ┬⌐ 1989, 1990 by Apple Computer, Inc., all rights reserved.     }
  111. {}
  112. { written by      : Anup Murarka                                                                                     }
  113. { AppleLink   : Skeptic                                                                                           }
  114. { modification history                                                                                           }
  115. {          Date            Initials                                      Comments                                     }
  116. {          ----            -----      -----------------------------------------------------}
  117. {       8/16/89          akm      first written                                                                     }
  118. {       5/21/90          ec             removed upper case converion for A/UX compatibility. }
  119. {                                           Changed version to 1.1.  added error checking when adding }
  120. {                                           to result handle, added code to disposhandle if we bail   }
  121. {                                           because of an error.                                                          }
  122. {       5/23/90          ec         assume user wants 'BOTH' if only one parameter passed}
  123. {}
  124. unit FolderContents;
  125.  
  126. interface
  127.  
  128.     uses
  129.         HyperXCmd;
  130.  
  131.     procedure MAIN (paramPtr: XCmdPtr);
  132.  
  133. implementation
  134.  
  135.     procedure FolderContents (paramPtr: XCmdPtr);
  136.     FORWARD;
  137.  
  138.     procedure MAIN (paramPtr: XCmdPtr);
  139.     begin
  140.         FolderContents(paramPtr);
  141.     end;
  142.  
  143.     procedure reportToUser (paramPtr: XCmdPtr;
  144.                                     msgStr: str255);
  145. {}
  146. { report something back to the user.  }
  147. { the last parameter (optional) to an external may contain }
  148.  { "noDialog" or "noDialog:GlobalName".  GlobalName is the name }
  149.  { of a HyperTalk global variable into which error messages will be }
  150.  { placed.  we've decided to use this approach to avoid confusing }
  151. { an error message with a valid result being returned from an XFCN. }
  152. {}
  153.         var
  154.             tempStr: str255;
  155.     begin
  156. {check the last param to see if the user requested that}
  157. { we suppress the error dialog }
  158.         ZeroToPas(paramPtr, paramPtr^.params[paramPtr^.paramCount]^, tempStr);
  159.         UprString(tempStr, true);
  160.         if pos('NODIALOG', tempStr) = 0 then
  161.     { no special error handling specified, throw up a dialog and return the error message }
  162.             begin
  163.                 SendCardMessage(paramPtr, concat('answer "', msgStr, '"'));
  164.                 paramPtr^.returnValue := PasToZero(paramPtr, msgStr);
  165.             end
  166.         else if (pos(':', tempStr) > 0) then
  167.     { requested global AND noDialog so we fill in the global and return empty }
  168.             begin
  169.                 tempStr := copy(tempStr, pos(':', tempStr) + 1, length(tempStr));
  170.                                                         { get the name of the HC global  to fill }
  171.                 SetGlobal(paramPtr, tempStr, PasToZero(paramPtr, msgStr));
  172.                                                         { and fill it }
  173.                 paramPtr^.returnValue := PasToZero(paramPtr, '');  { return empty }
  174.             end
  175.         else
  176.     { requested noDialog only so we return the error condition as the result }
  177.             paramPtr^.returnValue := PasToZero(paramPtr, msgStr);
  178.     end;      { procedure }
  179.  
  180.     function AskedForHelp (paramPtr: XCmdPtr;
  181.                                     syntaxMsg: Str255;
  182.                                     copyrightMsg: Str255): boolean;
  183. {   check to see if the user sent a '?' or a '!' as }
  184. { the only parameter. if so we will respond with }
  185. { the calling syntax or the copyright/version info }
  186. { for this external }
  187. {}
  188.         var
  189.             firstStr: str255;
  190.     begin
  191.         askedForHelp := false;
  192.         if paramPtr^.paramCount = 1 then
  193.             begin
  194.                 ZeroToPas(paramPtr, paramPtr^.params[1]^, firstStr);
  195.                     { what is the first param? }
  196.                 if firstStr = '?' then
  197.                     begin
  198.                         reportToUser(paramPtr, syntaxMsg);
  199.                         askedForHelp := true
  200.                     end   { asked for help }
  201.                 else if firstStr = '!' then
  202.                     begin
  203.                         reportToUser(paramPtr, copyRightMsg);
  204.                         askedForHelp := true
  205.                     end;      { asked for copyright info }
  206.             end;      { one parameter passed }
  207.     end;      { function }
  208.  
  209.     function LongToString (paramPtr: XCmdPtr;
  210.                                     num: LONGINT): Str255;
  211. { why, oh why did dan write this one as a procedure??? }
  212.         var
  213.             tempStr: str255;
  214.     begin
  215.         LongToStr(paramPtr, num, tempStr);
  216.         LongToString := tempStr;
  217.     end;
  218.  
  219.     function NumberToString (paramPtr: XCmdPtr;
  220.                                     num: LONGINT): Str255;
  221. { use the toolbox call rather than HC's }
  222.         var
  223.             tempStr: str255;
  224.     begin
  225.         NumToString(num, tempStr);
  226.         NumberToString := tempStr;
  227.     end;
  228.  
  229.     procedure reportResError (paramPtr: XCmdPtr;
  230.                                     errorNum: integer);
  231.         var
  232.             errMsg, tempName: str255;
  233.     begin
  234.         case errorNum of                      { what caused the problem? }
  235.             -0: 
  236.                 errMsg := 'no error.';
  237.             -36: 
  238.                 errMsg := 'I/O Error.';
  239.             -37: 
  240.                 errMsg := 'bad file name or volume name.';
  241.             -38: 
  242.                 errMsg := 'file not open.';
  243.             -39: 
  244.                 errMsg := 'that file has no resource fork.';
  245.             -42: 
  246.                 errMsg := 'too many files open.';
  247.             -43: 
  248.                 errMsg := 'file not found.';
  249.             -45, -54, -61: 
  250.                 errMsg := 'file locked.';
  251.             -47, -49: 
  252.                 errMsg := 'file is busy.';
  253.             -53: 
  254.                 errMsg := 'that volume is not on line.';
  255.             -108: 
  256.                 errMsg := 'not enough room in heap zone.';
  257.             -120: 
  258.                 errMsg := 'directory not found.';
  259.             -121: 
  260.                 errMsg := 'too many working directories open.';
  261.             -127: 
  262.                 errMsg := 'internal file system error.';
  263.             -192: 
  264.                 errMsg := 'resource not found.';
  265.             -193: 
  266.                 errMsg := 'file not found.';
  267.             otherwise
  268.                 errMsg := concat('unexpected error #', NumberToString(paramPtr, errorNum));
  269.         end;          { case }
  270.  
  271.         errMsg := concat('Sorry, ', errMsg);
  272.         reportToUser(paramPtr, errMsg);
  273.         { return the error message }
  274.     end;          { function }
  275.  
  276.     function getVolRefNum (pathName: str255): integer;
  277.     { function to return the volume reference number of the volume specified in the pathName}
  278.     { parameter.  Will automatically strip any trailing directory/file names}
  279.         var
  280.             paramBlock: HParamBlockRec;
  281.             errorCode: OSerr;
  282.     begin
  283.         if pos(':', pathName) = 0 then
  284.             pathName := concat(pathName, ':')
  285.         else
  286.             pathName := copy(pathName, 1, pos(':', pathName));
  287.         with paramBlock do
  288.             begin
  289.                 ioCompletion := nil;
  290.                 ioNamePtr := @pathName;
  291.                 ioVRefNum := 0;
  292.                 ioVolIndex := -1;
  293.         { if volindex is zero the file manager will try to get to the volume}
  294.         { through the ioVRefNum ΓÇö not a good thing here as that is what we don't know! }
  295.             end;
  296.         errorCode := PBHGetVInfo(@paramBlock, FALSE);
  297.         if errorCode <> noErr then
  298.             getVolRefNum := -1
  299.         else
  300.             getVolRefNum := paramBlock.ioVRefNum;
  301.     end;
  302.  
  303.     function BitTest (AddressToCheck: ptr;
  304.                                     TotalBits: integer;
  305.                                     BitToTest: longint): boolean;
  306.     { function that allows caller to use std. 68000 bit notation instead of the Toolbox's reversed notation}
  307.     { example:  bit 0 (the least significant bit) in a byte is bit 7 in the Toolbox's notation}
  308.     begin
  309.         BitTest := BitTst(AddressToCheck, TotalBits - 1 - BitToTest);
  310.     end;
  311.  
  312.     function AppendString (h: Handle;
  313.                                     newStr: Str255): OSErr;
  314.     { stick the string onto the back of the handle }
  315.     begin
  316.         AppendString := PtrAndHand(Ptr(ORD4(@newStr) + 1), h, LENGTH(newStr));
  317.     end;
  318.  
  319.     function getParams (paramPtr: XCmdPtr;
  320.                                     var PathToSearch: str255;
  321.                                     var LookForFiles, LookForFolders: boolean): boolean;
  322.     { function to get the parameters and validate them.  Returns boolean instructing}
  323.     { the main procedure to continue if the parameters passed are valid.  Also returns}
  324.     { syntax messages if asked for by the user.}
  325.         var
  326.             WhatToLookFor: str255;
  327.             numParams: integer;
  328.             inputCh: str255;
  329.             syntaxStr, copyrightStr: str255;
  330.  
  331.     begin
  332.         getParams := true;               {Initially, assume the parameters are valid.}
  333.         syntaxStr := 'FolderContents(pathname ┬½,ΓÇ£FilesΓÇ¥|ΓÇ£FoldersΓÇ¥|ΓÇ£BothΓÇ¥┬╗ ┬½,ΓÇ£nodialogΓÇ¥:errGlobal┬╗)';
  334.         copyrightStr := '┬⌐ 1989,1990 Apple Computer, Inc., v.1.1, by Anup Murarka';
  335.  
  336.         { Check for syntax or copyright requests}
  337.         if AskedForHelp(paramPtr, syntaxStr, copyrightStr) then
  338.             begin
  339.                 getParams := false;
  340.                 exit(getParams);
  341.             end;
  342.  
  343.         { Check parameter count}
  344.         numParams := paramPtr^.paramCount;
  345.         if (numParams < 1) or (numParams > 3) then {check that we have the proper number of parameters}
  346.             begin
  347.                 getParams := false;
  348.                 reportToUser(paramPtr, syntaxStr);
  349.                 exit(getParams);
  350.             end;
  351.  
  352.     { Get parameter 1, where to look }
  353.         ZeroToPas(paramPtr, paramPtr^.Params[1]^, PathToSearch);
  354.  
  355.         if numParams = 1 then              { default is to look for both }
  356.             whatToLookFor := 'BOTH'
  357.         else
  358.             begin
  359.     { Get parameter 2, what to look for }
  360.                 ZeroToPas(paramPtr, paramPtr^.Params[2]^, whatToLookFor);
  361.                 UprString(whatToLookFor, true);          { convert to uppercase }
  362.  
  363.                 if (whatToLookFor <> 'FILES') and (whatToLookFor <> 'FOLDERS') and (whatToLookFor <> 'BOTH') then
  364.                     begin
  365.                         getParams := false;
  366.                         reportToUser(paramPtr, syntaxStr);
  367.                     end;
  368.             end;
  369.  
  370.         LookForFolders := true;            {assume that everything should be returned}
  371.         LookForFiles := true;
  372.         if (whatToLookFor = 'FILES') then
  373.             LookForFolders := False
  374.         else if (whatToLookFor = 'FOLDERS') then
  375.             LookForFiles := False;
  376.     end;          {GetParams}
  377.  
  378.     procedure FolderContents (paramPtr: XCmdPtr);
  379.         var
  380.             filelist: handle;
  381.             getParamsOK, ItIsAFolder, LookForFiles, LookForFolders: boolean;
  382.             FileName: str255;
  383.             paramBlock: CInfoPBRec;
  384.             errorCode: OSerr;
  385.             dirIndex: integer;
  386.             DirToScan: longint;
  387.  
  388.     begin    { FolderContents}
  389.     { fetch and validate the passed parameters}
  390.         getParamsOK := getParams(paramPtr, fileName, lookForFiles, lookForFolders);
  391.         if not (getParamsOK) then
  392.             exit(FolderContents);
  393.  
  394.     { Initialize the parameter block.  Since we have the full pathname, no other field is really needed, but}
  395.     { future use of the paramBlock will need the vRefNum since PathToSearch won't always contain the}
  396.     { full pathname.}
  397.         zeroBytes(paramPtr, @paramBlock, sizeOf(paramBlock));
  398.         paramBlock.ioNamePtr := @fileName;
  399.         paramBlock.ioVRefNum := getVolRefNum(fileName);
  400.  
  401.         errorCode := PBGetCatInfo(@paramBlock, FALSE);
  402.         if errorCode <> noErr then
  403.             begin
  404.                 reportToUser(paramPtr, 'Sorry, directory not found.');
  405.                 exit(FolderContents);
  406.             end;
  407.         if not bitTest(@paramBlock.ioFlAttrib, 8, 4) then
  408.             begin
  409.                 reportToUser(paramPtr, 'Sorry, I handle FOLDER contents, not file contents!');
  410.                 exit(FolderContents);
  411.             end;
  412.  
  413.     { Initialize the handle that will contain the directory listing}
  414.         filelist := NewHandle(0);
  415.  
  416.         dirIndex := 1;
  417.         DirToScan := paramBlock.ioDrDirID;
  418.         repeat      {repeat until all files/folders within dirIDToScan are noted}
  419.             FileName := '';      { zero the name so that it is not used to find the next file}
  420.             paramBlock.ioFDirIndex := dirIndex;          { ioFDirIndex is incremented to point to the next file/folder}
  421.             paramBlock.ioDrDirID := DirToScan;          { this has to be reset each iteration}
  422.             errorCode := PBGetCatInfo(@paramBlock, FALSE);        { get the file/folder info}
  423.             if errorCode = noErr then          { if something was found: }
  424.                 begin
  425.                     ItIsAFolder := bitTest(@paramBlock.ioFlAttrib, 8, 4);
  426.                     if ItIsAFolder then
  427.                         FileName := concat(FileName, ':');
  428.                     if (ItIsAFolder and LookForFolders) or ((not ItIsAFolder) and LookForFiles) then
  429.                         errorCode := appendString(filelist, concat(FileName, chr(13)));        {add to the list}
  430.                     if errorCode <> noErr then
  431.                         begin
  432.                             reportToUser(paramPtr, 'Sorry, could not build list.');
  433.                             if fileList <> nil then
  434.                                 DisposHandle(fileList);
  435.                             exit(FolderContents);
  436.                         end;
  437.                 end;
  438.             dirIndex := dirIndex + 1;
  439.         until errorCode <> noErr;
  440.  
  441.     { Now append a null character onto the end of the result}
  442.         errorCode := appendString(filelist, chr(0));
  443.         if errorCode <> noErr then
  444.             begin
  445.                 reportToUser(paramPtr, 'Sorry, could not build list.');
  446.                 if fileList <> nil then
  447.                     DisposHandle(fileList);
  448.                 exit(FolderContents);
  449.             end;
  450.         paramPtr^.returnValue := filelist;
  451.     end;
  452. end.